package com.example.util;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;

/**
 * 日期时间工具类
 * 
 * @author Means
 * @since 2025-10-27
 */
public class DateTimeUtils {
    
    /** 默认日期时间格式 */
    public static final String DEFAULT_DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
    
    /** 默认日期格式 */
    public static final String DEFAULT_DATE_PATTERN = "yyyy-MM-dd";
    
    /** 默认时间格式 */
    public static final String DEFAULT_TIME_PATTERN = "HH:mm:ss";
    
    /** 紧凑日期时间格式 */
    public static final String COMPACT_DATETIME_PATTERN = "yyyyMMddHHmmss";
    
    /** 默认时区 */
    public static final ZoneId DEFAULT_ZONE_ID = ZoneId.of("Asia/Shanghai");
    
    private static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern(DEFAULT_DATETIME_PATTERN);
    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern(DEFAULT_DATE_PATTERN);
    private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern(DEFAULT_TIME_PATTERN);
    private static final DateTimeFormatter COMPACT_DATETIME_FORMATTER = DateTimeFormatter.ofPattern(COMPACT_DATETIME_PATTERN);
    
    /**
     * 获取当前时间
     * 
     * @return 当前时间
     */
    public static LocalDateTime now() {
        return LocalDateTime.now(DEFAULT_ZONE_ID);
    }
    
    /**
     * 获取当前日期
     * 
     * @return 当前日期
     */
    public static LocalDate today() {
        return LocalDate.now(DEFAULT_ZONE_ID);
    }
    
    /**
     * 获取今天开始时间 00:00:00
     * 
     * @return 今天开始时间
     */
    public static LocalDateTime startOfToday() {
        return today().atStartOfDay();
    }
    
    /**
     * 获取今天结束时间 23:59:59
     * 
     * @return 今天结束时间
     */
    public static LocalDateTime endOfToday() {
        return today().atTime(LocalTime.MAX);
    }
    
    /**
     * 获取指定日期的开始时间 00:00:00
     * 
     * @param date 日期
     * @return 开始时间
     */
    public static LocalDateTime startOfDay(LocalDate date) {
        return date.atStartOfDay();
    }
    
    /**
     * 获取指定日期的结束时间 23:59:59
     * 
     * @param date 日期
     * @return 结束时间
     */
    public static LocalDateTime endOfDay(LocalDate date) {
        return date.atTime(LocalTime.MAX);
    }
    
    /**
     * 格式化日期时间为字符串
     * 
     * @param dateTime 日期时间
     * @return 格式化后的字符串
     */
    public static String format(LocalDateTime dateTime) {
        return dateTime == null ? null : dateTime.format(DATETIME_FORMATTER);
    }
    
    /**
     * 格式化日期为字符串
     * 
     * @param date 日期
     * @return 格式化后的字符串
     */
    public static String format(LocalDate date) {
        return date == null ? null : date.format(DATE_FORMATTER);
    }
    
    /**
     * 格式化时间为字符串
     * 
     * @param time 时间
     * @return 格式化后的字符串
     */
    public static String format(LocalTime time) {
        return time == null ? null : time.format(TIME_FORMATTER);
    }
    
    /**
     * 格式化日期时间为紧凑字符串
     * 
     * @param dateTime 日期时间
     * @return 格式化后的字符串（如：20251027153045）
     */
    public static String formatCompact(LocalDateTime dateTime) {
        return dateTime == null ? null : dateTime.format(COMPACT_DATETIME_FORMATTER);
    }
    
    /**
     * 自定义格式化日期时间
     * 
     * @param dateTime 日期时间
     * @param pattern 格式模式
     * @return 格式化后的字符串
     */
    public static String format(LocalDateTime dateTime, String pattern) {
        return dateTime == null ? null : dateTime.format(DateTimeFormatter.ofPattern(pattern));
    }
    
    /**
     * 解析日期时间字符串
     * 
     * @param dateTimeStr 日期时间字符串
     * @return 日期时间对象
     */
    public static LocalDateTime parseDateTime(String dateTimeStr) {
        return dateTimeStr == null ? null : LocalDateTime.parse(dateTimeStr, DATETIME_FORMATTER);
    }
    
    /**
     * 解析日期字符串
     * 
     * @param dateStr 日期字符串
     * @return 日期对象
     */
    public static LocalDate parseDate(String dateStr) {
        return dateStr == null ? null : LocalDate.parse(dateStr, DATE_FORMATTER);
    }
    
    /**
     * 计算两个日期时间之间的天数差
     * 
     * @param start 开始时间
     * @param end 结束时间
     * @return 天数差
     */
    public static long daysBetween(LocalDateTime start, LocalDateTime end) {
        return ChronoUnit.DAYS.between(start, end);
    }
    
    /**
     * 计算两个日期时间之间的小时差
     * 
     * @param start 开始时间
     * @param end 结束时间
     * @return 小时差
     */
    public static long hoursBetween(LocalDateTime start, LocalDateTime end) {
        return ChronoUnit.HOURS.between(start, end);
    }
    
    /**
     * 计算两个日期时间之间的分钟差
     * 
     * @param start 开始时间
     * @param end 结束时间
     * @return 分钟差
     */
    public static long minutesBetween(LocalDateTime start, LocalDateTime end) {
        return ChronoUnit.MINUTES.between(start, end);
    }
    
    /**
     * 判断时间是否在指定范围内
     * 
     * @param time 待判断时间
     * @param start 开始时间
     * @param end 结束时间
     * @return 是否在范围内
     */
    public static boolean isBetween(LocalDateTime time, LocalDateTime start, LocalDateTime end) {
        return !time.isBefore(start) && !time.isAfter(end);
    }
    
    /**
     * 判断是否是今天
     * 
     * @param dateTime 日期时间
     * @return 是否是今天
     */
    public static boolean isToday(LocalDateTime dateTime) {
        return dateTime != null && dateTime.toLocalDate().equals(today());
    }
    
    /**
     * LocalDateTime转时间戳（毫秒）
     * 
     * @param dateTime 日期时间
     * @return 时间戳
     */
    public static long toTimestamp(LocalDateTime dateTime) {
        return dateTime.atZone(DEFAULT_ZONE_ID).toInstant().toEpochMilli();
    }
    
    /**
     * 时间戳（毫秒）转LocalDateTime
     * 
     * @param timestamp 时间戳
     * @return 日期时间
     */
    public static LocalDateTime fromTimestamp(long timestamp) {
        return LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), DEFAULT_ZONE_ID);
    }
}

